/*
   Copyright (C) 2011 Roman Belov <romblv@gmail.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _H_PARSER_
#define _H_PARSER_

#include "util/list.h"

struct port;
struct module;

struct link {
	list_node_t		_node;
	list_node_t		list;		/* list of linked ports */
	struct module		*owner;		/* link to the module */
	struct port		*master;	/* master of the link */
	int			val;		/* value */
	int			pval;		/* propagated value */
};

struct port {
	list_node_t		_node;
	const char		*id;		/* identifier */
	struct link		*lni;		/* internal link */
	struct link		*lne;		/* external link */
	struct module		*owner;		/* link to the module */
	int			bits;		/* in/out bits */
};

struct module {
	list_node_t		_node;
	const char		*id;		/* identifier */
	const char		*lid;		/* local id */
	list_node_t		local;		/* list of local modules */
	list_node_t		port;		/* list of ports */
	list_node_t		link;		/* list of links */
	list_node_t		spec;		/* list of specs */
	int (* calc) (struct module *m);	/* calc function */
	struct port		**lmap;		/* table to convert a number to the port */
	void			*cust;		/* custom data */
};

/*
    The following diagram illustrates the linkage of core structures.

    +--------------------| struct module |---------------------+
    |                                                          |
   =P= <--- (struct port)                  (struct link)       |
    |                     +--M---+              |              |
    |                    =P=     |                             |
   =P=----| L |           |     =P=-----------| L |-----------=P=
    |     | L |----------=P=     |            | L |--\         |
    |                     +------+                    \        |
    |       ^                 ^                        \       |
    |       |                 |                         \      |
    |    (struct link)   (struct module)                 -----=P=
    |                     It is a local module or child        |
    |                                                          |
    +----------------------------------------------------------+

 */

enum {
	SPEC_NULL,
	SPEC_STRING,
	SPEC_INT
};

struct spec {
	list_node_t		_node;
	const char		*id;		/* identifier */
	int			type;		/* spec type */
	union {
		const char	*s;
		int		i;
	} val;					/* spec value */
	struct module		*owner;		/* link to the module */
};

struct parser {
	list_node_t		list;		/* list of modules */
	list_node_t		file;		/* list of parsed files */
	int			error;		/* error number */
};

struct parser *
parser_open(const char *file,
		struct parser *p,
		const char *from_file,
		int line);

void
parser_close(struct parser *p);

struct module *
module_find(struct parser *p, const char *id);

struct spec *
spec_find(struct module *m, const char *id);

#endif /* _H_PARSER_ */

